package at.tuwien.seminar.scrum1.view.reservation.create;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import at.tuwien.seminar.scrum1.converter.RoomConverter;
import at.tuwien.seminar.scrum1.model.Bill;
import at.tuwien.seminar.scrum1.view.bill.list.BillList;
import at.tuwien.seminar.scrum1.view.customer.list.CustomerList;
import at.tuwien.seminar.scrum1.view.room.list.RoomList;
import com.sun.org.apache.bcel.internal.generic.NEW;
import org.apache.wicket.Component;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
import org.apache.wicket.extensions.markup.html.form.DateTextField;
import org.apache.wicket.extensions.yui.calendar.DatePicker;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.*;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.validation.validator.MinimumValidator;
import org.apache.wicket.validation.validator.NumberValidator;
import org.apache.wicket.validation.validator.RangeValidator;
import org.apache.wicket.validation.validator.StringValidator;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;

import at.tuwien.seminar.scrum1.model.Customer;
import at.tuwien.seminar.scrum1.model.Reservation;
import at.tuwien.seminar.scrum1.model.Room;
import at.tuwien.seminar.scrum1.proxies.CustomerProxy;
import at.tuwien.seminar.scrum1.proxies.ReservationProxy;
import at.tuwien.seminar.scrum1.proxies.RoomProxy;
import at.tuwien.seminar.scrum1.validator.CustomerValidator;
import at.tuwien.seminar.scrum1.view.reservation.list.ReservationList;

public class CreateReservation extends WebPage {

    private DropDownChoice roomDropDown;

    private Date startDt, endDt;
    private DateFormat df = new SimpleDateFormat("dd.MM.yyyy");


    private String room;

	@SuppressWarnings("serial")
	public CreateReservation()
	{

         add(new Link<Room>("roomLink") {

			@Override
			public void onClick() {
				setResponsePage(new RoomList());
			}

		});
		add(new Link<Customer>("customerLink") {

			@Override
			public void onClick() {
				setResponsePage(new CustomerList());
			}

		});

        add(new Link<Customer>("reservationLink") {

			@Override
			public void onClick() {
				setResponsePage(new ReservationList(ReservationProxy.getInstance().getAll()));
			}

		});

         add(new Link<Bill>("billLink") {

			@Override
			public void onClick() {
				setResponsePage(new BillList());
			}

		});

		Reservation newReservation = new Reservation();
		List<Integer> numbers = Arrays.asList(new Integer[] { 0, 1, 2 });
		
		final Form<Reservation> form = new Form<Reservation>("reservationForm", new CompoundPropertyModel<Reservation>(newReservation))
		{
			@Override
			protected void onSubmit()
			{
				Reservation reservation= getModelObject();
				List<Customer> customerObjects= new ArrayList<Customer>();	
				
				FormComponent fc1= (FormComponent)this.get("customers:0:firstName");
				FormComponent fc2= (FormComponent)this.get("customers:1:firstName");
				FormComponent fc3= (FormComponent)this.get("customers:2:firstName");

				HashSet<String> ids= new HashSet<String>();

				int count= 0;
				FormComponent[] components = new FormComponent[] { fc1, fc2, fc3 };

				for(int i=0; i <= 2;i++){
                    if (components[i].getInput() != null && !components[i].getInput().equals("")) {
                        String id= CustomerProxy.getInstance().extractId(components[i].getInput()).toString();
                        customerObjects.add(CustomerProxy.getInstance().getById(Long.parseLong(id)));
                    }
                }
				reservation.setCustomers(customerObjects);

                reservation.setRoom(RoomProxy.getInstance().getById(RoomProxy.getInstance().extractId(room)));

				//find out roomprice
				double price=0.0;


				if(customerObjects.size() == 1){
					//singleroom
					if(reservation.getChildren() == 0)
						price= reservation.getRoom().getPriceSingleRoom();
					if(reservation.getChildren() == 1)
						price= reservation.getRoom().getPriceSingleRoomWithChild();
					if(reservation.getChildren() == 2)
						price= reservation.getRoom().getPriceSingleRoomWithTwoChild();
				}else if(customerObjects.size() == 2){
					//doubleroom
					if(reservation.getChildren() == 0)
						price= reservation.getRoom().getPriceDoubleRoom();
					if(reservation.getChildren() == 1)
						price= reservation.getRoom().getPriceDoubleRoomWithChild();
				}else{
                    price= reservation.getRoom().getPriceTripleRoom();
				}
				
				reservation.setPrice(price);			

				//set response page
                ReservationProxy.getInstance().insertReservation(reservation);

				setResponsePage(new ReservationList(ReservationProxy.getInstance().getAll()));
			}

			@SuppressWarnings("rawtypes")
			@Override
			protected void onValidate() {
				super.onValidate();
				
				//validate correct customers
				FormComponent fc1= (FormComponent)this.get("customers:0:firstName");
				FormComponent fc2= (FormComponent)this.get("customers:1:firstName");
				FormComponent fc3= (FormComponent)this.get("customers:2:firstName");
				
				HashSet<String> ids= new HashSet<String>();
				
				int count= 0;
				FormComponent[] components = new FormComponent[] { fc1, fc2, fc3 };
				
				for(int i=0; i <= 2;i++){
                    if (components[i].getInput() != null && !components[i].getInput().equals("")) {
                        String id= CustomerProxy.getInstance().extractId(components[i].getInput()).toString();

                        if(!id.equals("0") && !id.equals("")){
                            //if customer was added more than once
                            if(!ids.add(id)){
                                error("Kunde "+id+" wurde doppelt angegeben");
                            }
                            count++;
                        }
                    }
				}
				
				if(count < 1){
					error("mind. 1 Kunde ist notwendig");
				}
				
				//validate if startdate is before enddate
				FormComponent startFc= (FormComponent)this.get("startDate");
				FormComponent endFc= (FormComponent)this.get("endDate");
				DropDownChoice<Room> roomFc= (DropDownChoice<Room>)this.get("room");
				
				if(startFc.isValid() && endFc.isValid())
				{

					try {
						Date start= df.parse(startFc.getInput());
						Date end= df.parse(endFc.getInput());
						
						if(start.after(end))
							error("Von-Datum muss vor Bis-Datum liegen");
						else{							
							//check if room is available at that time
							if(roomFc.isValid()){
								try{
									Room room = RoomProxy.getInstance().getById(RoomProxy.getInstance().extractId(roomFc.getInput()));
									
									if(!ReservationProxy.getInstance().checkReservationDate(room, start, end))
										error("Dieses Zimmer ist in diesem Zeitraum bereits reserviert");
								}catch(NumberFormatException e){
									//nothing
								}
							}
						}
					} catch (ParseException e) {
						error("Fehler bei Von- und Bis-Datum Analyse");
					}				
				}
				
				//check if max persons is to low
				if(roomFc.isValid()){
					try{
						Room room = RoomProxy.getInstance().getById(RoomProxy.getInstance().extractId(roomFc.getInput()));
										
						int grownups=0;					
						//count grownups
						if(fc1.getInput()!= null && !fc1.getInput().equals("0"))
							grownups++;
						if(fc2.getInput()!= null && !fc2.getInput().equals("0"))
							grownups++;
						if(fc3.getInput()!= null && !fc3.getInput().equals("0"))
							grownups++;
						
						DropDownChoice<Integer> childrenFc= (DropDownChoice<Integer>) this.get("children");
						int children= Integer.parseInt(childrenFc.getInput());
												
						if(children+grownups > room.getMaxNumberOfPersons())
							error("Zimmer erlaubt nur "+room.getMaxNumberOfPersons()+ " Persone(n), es sind jedoch "+(children+grownups));
					}catch(NumberFormatException e){
						//nothing
					}
										
				}
			}
			
			
		};
			
		
		DatePicker startDatePicker = new DatePicker();
		DatePicker endDatePicker = new DatePicker();
		
		form.add(new DateTextField("startDate", "dd.MM.yyyy").setRequired(true).add(startDatePicker).add(new AjaxFormComponentUpdatingBehavior("onchange") {
            @Override
            protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) {
                FormComponent startFc= (FormComponent)form.get("startDate");

                try {
                    startDt = df.parse(startFc.getInput());
                } catch (Exception e) {

                }

                if (endDt != null && startDt != null) {
                    roomDropDown.setChoices(RoomProxy.getInstance().getFreeRooms(startDt, endDt));
                    ajaxRequestTarget.addComponent(roomDropDown);
                }
            }
        }));
		form.add(new DateTextField("endDate", "dd.MM.yyyy").setRequired(true).add(endDatePicker).add(new AjaxFormComponentUpdatingBehavior("onchange") {
            @Override
            protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) {
                FormComponent endFc= (FormComponent)form.get("endDate");

                try {
                    endDt = df.parse(endFc.getInput());
                } catch (Exception e) {

                }

                if (endDt != null && startDt != null) {
                    roomDropDown.setChoices(RoomProxy.getInstance().getFreeRooms(startDt, endDt));
                    ajaxRequestTarget.addComponent(roomDropDown);
                }
            }
        }));
				
		form.add(new DropDownChoice<Integer>("children", numbers).setNullValid(false));
		
		
		List<Room> rooms = RoomProxy.getInstance().getAll();

        roomDropDown = new DropDownChoice<String>("room", new PropertyModel<String>(this, "room"), new AbstractReadOnlyModel<List<? extends String>>() {
            @Override
            public List<? extends String> getObject() {
                return new ArrayList<String>();
            }
        });

        roomDropDown.setNullValid(false);
        roomDropDown.setRequired(true);
        roomDropDown.setOutputMarkupId(true);

        form.add(roomDropDown);
		
		
		form.add(new TextField<Double>("discount").
				setRequired(false).
				// replace!
				add(NumberValidator.range(0,100)));
		
		//customer fields
		newReservation.getCustomers().add(new Customer());
		newReservation.getCustomers().add(new Customer());
		newReservation.getCustomers().add(new Customer());
		
		
		@SuppressWarnings({ "unchecked", "rawtypes" })
		ListView customersList= new ListView("customers"){
			protected void populateItem(ListItem item){
				Customer customer= (Customer)item.getModelObject();
				
				item.setModel(new CompoundPropertyModel<Customer>(customer));
                item.add( new AutoCompleteTextField<String>("firstName") {
                    @Override
                    protected Iterator<String> getChoices(String input) {
                        List<String> customers = new ArrayList<String>();

                        for (Customer customer : CustomerProxy.getInstance().getAll()) {
                            String searchString = customer.getFirstName() + " " + customer.getLastName() + " [" + customer.getId() + "]";

                            if (searchString.contains(input)) {
                                customers.add(searchString);
                            }
                        }

                        return customers.iterator();
                    }

                }.add(new CustomerValidator()));
			}
		}.setReuseItems(true);		
		
		form.add(customersList);
		//form.add(new CustomerListValidator(customersList));
		
		
		/*
		form.add(new TextField<Long>("room").
				setRequired(false));
		*/
		form.add(new Button("submit"));
		form.add(new FeedbackPanel("feedback"));
		
		add(form);
		
		add(new Link<Reservation>("back") {
			@Override
			public void onClick() {
				setResponsePage(new ReservationList(ReservationProxy.getInstance().getAll()));

			}
		});
	}

    public String getRoom() {
           return room;
       }

       public void setRoom(String room) {
           this.room = room;
       }

}
